﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Google.OrTools.ConstraintSolver;

namespace Study.GoogleOptimizationTools.ConsoleApp.Examples
{
    public class ExampleLetterPuzzle
    {
        /// <summary>
        /// 字母谜题：求下列字母等式成立的各个字母代表的数字
        /// ================
        ///       C P
        /// +     I S
        /// +   F U N
        /// ---------
        /// = T R U E
        /// ================
        /// </summary>
        public static void Example_1()
        {
            int baseNumber = 10;

            var solver = new Solver("Example_1");

            //定义变量，每个不同的字母定义一个变量即可。
            //c,i,f,t不可能为0，其他的范围都是0-9
            var c = solver.MakeIntVar(1, baseNumber - 1, "c");
            var p = solver.MakeIntVar(0, baseNumber - 1, "p");

            var i = solver.MakeIntVar(1, baseNumber - 1, "i");
            var s = solver.MakeIntVar(0, baseNumber - 1, "s");

            var f = solver.MakeIntVar(1, baseNumber - 1, "f");
            var u = solver.MakeIntVar(0, baseNumber - 1, "u");
            var n = solver.MakeIntVar(0, baseNumber - 1, "n");

            var t = solver.MakeIntVar(1, baseNumber - 1, "t");
            var r = solver.MakeIntVar(0, baseNumber - 1, "r");
            var e = solver.MakeIntVar(0, baseNumber - 1, "e");

            var xNumbers = new List<IntVar>(10);
            xNumbers.AddRange(new[] { c, p, i, s, f, u, n, t, r, e });


            ////定义每行的数
            var term1 = solver.MakeSum(solver.MakeProd(c, 10), p); //可用 c*10+p
            var term2 = solver.MakeSum(solver.MakeProd(i, 10), s); //
            var term3 = f * 100 + u * 10 + n; //
            var term4 = t * 1000 + r * 100 + u * 10 + e;

            //定义约束
            var sumConstraint = solver.MakeEquality(term1 + term2 + term3, term4); //可用 term1 + term2 + term3 == term4

            ////每个字母不一样
            var diffConstraint = solver.MakeAllDifferent(xNumbers.ToArray());

            solver.Add(sumConstraint);
            solver.Add(diffConstraint);

            var db = solver.MakePhase(xNumbers.ToArray(), Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE);

            solver.NewSearch(db);

            while (solver.NextSolution())
            {
                Console.WriteLine("*************************");
                Console.WriteLine($"{c.Value()}{p.Value()}".PadLeft(5));
                Console.WriteLine($"{i.Value()}{s.Value()}".PadLeft(5));
                Console.WriteLine($"{f.Value()}{u.Value()}{n.Value()}".PadLeft(5));

                Console.WriteLine("-".PadLeft(5, '-'));

                Console.WriteLine($"{t.Value()}{r.Value()}{u.Value()}{e.Value()}".PadLeft(5));
            }

       
        }



    }
}
